﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Microsoft.Windows.Controls.Ribbon;
using AppfabricAdministrator.Commands;
using AppfabricAdministrator.Entities;
using Microsoft.ApplicationServer.Caching.AdminApi;

namespace AdminMainUI
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : RibbonWindow
    {
        #region Private Variables

        private PowershellCommands powerShellComm { get; set; }

        #endregion

        #region Initializers

        public MainWindow()
        {
            InitializeComponent();
            this.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
            this.Title = "Appfabric Cluster Administrator 1.1.0";
            UseCacheCluster();
        }

        #endregion

        #region Cluster Operations

        private void UseCacheCluster()
        {
            AppfabricAdministrator.Commands.Cluster.UseCluster clusterCommand = new AppfabricAdministrator.Commands.Cluster.UseCluster();
            if (clusterCommand.Execute())
            {
                powerShellComm = new PowershellCommands(clusterCommand);
                if (powerShellComm != null)
                {
                    powerShellComm.Message = new Message();
                    powerShellComm.Message.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(message_PropertyChanged);
                    powerShellComm.GetCacheHosts();
                    powerShellComm.GetCache();
                    rgClusterOperations.Visibility = System.Windows.Visibility.Visible;
                    rgClusterImport.Visibility = System.Windows.Visibility.Visible;
                    rgClusterAdvanced.Visibility = System.Windows.Visibility.Visible;
                    UpdateCacheTab();
                    UpdateHostsTab();
                }
                else
                {
                    CreatePowershellInstance();
                    powerShellComm.Message.SetMessage("Cannot cannot to cluster. Try using manual connect",MessageType.Error);
                }
            }
            else
            {
                CreatePowershellInstance();
                powerShellComm.Message.SetMessage("Machine does not have Appfabric 1.1 client installed.", MessageType.Error);
            }
        }

        private void CreatePowershellInstance()
        {
            powerShellComm = new PowershellCommands();
            powerShellComm.Message.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(message_PropertyChanged);
        }

        //Connect button click
        private void RibbonButton_Click(object sender, RoutedEventArgs e)
        {
            ConnectWindow w = new ConnectWindow();
            w.Owner = this;
            var comm = w.OpenConfigDialog();
            if (comm!= null)
            {
                powerShellComm = comm;
                rgClusterOperations.Visibility = System.Windows.Visibility.Visible;
                rgClusterImport.Visibility = System.Windows.Visibility.Visible;
                rgClusterAdvanced.Visibility = System.Windows.Visibility.Visible;
                UpdateCacheTab();
                UpdateHostsTab();
            }
        }

        /// <summary>
        /// Start Cache Cluster
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void rbCcStart_Click(object sender, RoutedEventArgs e)
        {
            powerShellComm.StartCacheCluster();
            UpdateHostsTab();
        }

        //Stop Cache Cluster
        private void rbCcStop_Click(object sender, RoutedEventArgs e)
        {
            powerShellComm.StopCacheCluster();
            UpdateHostsTab();
        }

        //Restart Cache Cluster
        private void rbCcRestart_Click(object sender, RoutedEventArgs e)
        {
            powerShellComm.RestartCacheCluster();
            UpdateHostsTab();
        }

        private void rbCcExport_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.Forms.FolderBrowserDialog dialog = new System.Windows.Forms.FolderBrowserDialog();
            if (!String.IsNullOrEmpty(GetNetworkFolder(dialog)))
            {
                powerShellComm.ExportConfig(dialog.SelectedPath);
            }
        }

        private void rbCcImport_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.Forms.OpenFileDialog dialog = new System.Windows.Forms.OpenFileDialog();
            dialog.Filter = "XML Config File (*.xml)|*.xml";
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                powerShellComm.ImportConfig(dialog.FileName);
            }
        }

        private void rbCcGC_Click(object sender, RoutedEventArgs e)
        {
            powerShellComm.InvokeGC();
        }

        private void rbCcSecurity_Click(object sender, RoutedEventArgs e)
        {
            ClusterSecurityWindow securityWindow = new ClusterSecurityWindow();
            securityWindow.Owner = this;
            var clusterCommand = securityWindow.ShowSecurityWindow();
            if (clusterCommand != null)
            {
                powerShellComm.SetSecurity(clusterCommand);
            }
        }

        private void rbCcAccess_Click(object sender, RoutedEventArgs e)
        {
            ClusterAccess access = new ClusterAccess(powerShellComm);
            access.Owner = this;
            access.ShowAccessWindow();
        }

        private String GetNetworkFolder(System.Windows.Forms.FolderBrowserDialog dialog)
        {
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                return dialog.SelectedPath;
            else
                return "";
        }

        #endregion

        #region Host Operations

        //Refresh Host List
        private void rbChRefresh_Click(object sender, RoutedEventArgs e)
        {
            powerShellComm.GetCacheHosts();
            UpdateHostsTab(false);
        }

        private void rbChStart_Click(object sender, RoutedEventArgs e)
        {
            String hostName = GetHostName();
            powerShellComm.StartHost(hostName, GetHostPort(hostName));
            rbChRefresh_Click(sender, e);
        }

        private void rbChStop_Click(object sender, RoutedEventArgs e)
        {
            String hostName = GetHostName();
            powerShellComm.StopHost(hostName, GetHostPort(hostName));
            rbChRefresh_Click(sender, e);
        }

        private void rbChRestart_Click(object sender, RoutedEventArgs e)
        {
            String hostName = GetHostName();
            powerShellComm.RestartHost(hostName, GetHostPort(hostName));
        }

        private Int32 GetHostPort(String _hostName)
        {
            return (from hostInfo in powerShellComm.adminEntity.Hosts
                    where hostInfo.HostName == _hostName
                    select hostInfo.PortNo).First();
        }

        private String GetHostName()
        {
            return (((from TreeViewItem item in tviHost.Items
                      where item.IsSelected
                      select item).First().Header as StackPanel).Children[1] as TextBlock).Text.TrimStart();
        }

        private void rbnGracefulRestart_Click(object sender, RoutedEventArgs e)
        {
            String hostName = GetHostName();
            powerShellComm.RestartHost(hostName, GetHostPort(hostName), true);
        }

        private void rbnGracefulStop_Click(object sender, RoutedEventArgs e)
        {
            String hostName = GetHostName();
            powerShellComm.StopHost(hostName, GetHostPort(hostName), true);
            UpdateHostsTab();
        }

        private void rbChConfig_Click(object sender, RoutedEventArgs e)
        {
            String hostName = GetHostName();
            HostConfig config = powerShellComm.GetHostConfig(hostName, GetHostPort(hostName));
            if (config != null)
            {
                HostConfigWindow hostConfigWindow = new HostConfigWindow(config);
                hostConfigWindow.Owner = this;
                var hostConfig = hostConfigWindow.SetHostConfig();
                if (hostConfig != null)
                {
                    powerShellComm.SetHostConfig(hostConfig);
                }
            }
        }

        #endregion

        #region Cache Operations

        //Add new cache
        private void rbCNew_Click(object sender, RoutedEventArgs e)
        {
            ConfigWindow cacheConfigWindow = new ConfigWindow();
            cacheConfigWindow.Owner = this;
            AppfabricAdministrator.Commands.Cache.NewCache newCache = cacheConfigWindow.CreateNewCache();
            if (newCache != null)
            {
                powerShellComm.AddNewCache(newCache);
                UpdateCacheTab();
            }
        }

        //Remove cache
        private void rbCRemove_Click(object sender, RoutedEventArgs e)
        {
            var cacheName = GetCacheName();
            powerShellComm.RemoveCache(cacheName);
            UpdateCacheTab();
        }

        //Refresh Cache List
        private void rbCRefresh_Click(object sender, RoutedEventArgs e)
        {
            powerShellComm.GetCache();
            UpdateCacheTab(false);
        }

        //Get Cache Statistics
        private void rbCStatistics_Click(object sender, RoutedEventArgs e)
        {
            var cacheName = GetCacheName();
            CacheStatistics statistics = powerShellComm.GetCacheStatistics(cacheName);
            if (statistics != null)
            {
                pnlCacheStatistics.Visibility = System.Windows.Visibility.Visible;
                lblSize.Content = statistics.Size;
                lblItemCount.Content = statistics.ItemCount;
                lblRegionCount.Content = statistics.RegionCount;
                lblInBandwidth.Content = statistics.IncomimgBandwidth;
                lblOutBandwidth.Content = statistics.OutgoingBandwidth;
                lblRegionCount.Content = statistics.RegionCount;
                lblRequestCount.Content = statistics.RequestCount;
                lblReadReqCount.Content = statistics.ReadRequestCount;
                lblWriteReqCount.Content = statistics.WriteRequestCount;

                lblCSHeader.Content = "Cache Statistics for " + statistics.CacheName;
                lblTimestamp.Content = DateTime.Now.ToString("hh:mm:ss.fff tt");
            }
        }

        private String GetCacheName()
        {
            return (((from TreeViewItem item in tviCache.Items
                      where item.IsSelected
                      select item).First().Header as StackPanel).Children[1] as TextBlock).Text.TrimStart();
        }

        //Get cache config
        private void rbCConfig_Click(object sender, RoutedEventArgs e)
        {
            var cacheName = GetCacheName();
            var cacheConfig = powerShellComm.GetCacheConfig(cacheName);
            if (cacheConfig != null)
            {
                ConfigWindow cacheConfigWindow = new ConfigWindow(cacheConfig);
                cacheConfigWindow.Owner = this;
                var newCacheConfig = cacheConfigWindow.SetCacheConfig();
                if (newCacheConfig != null)
                {
                    powerShellComm.AddNewCache(newCacheConfig);
                }
            }
        }

        #endregion

        #region UI Operations

        private void UpdateCacheTab(bool hideTab = true)
        {
            tviCache.Items.Clear();
            foreach (CacheInfo cache in powerShellComm.adminEntity.Cache)
            {
                TreeViewItem cacheItem = CreateTreeViewItem(cache.CacheName, "Database-16.png");
                tviCache.Items.Add(cacheItem);
            }
            tviCache.IsExpanded = true;
            if (hideTab)
                rtCache.Visibility = System.Windows.Visibility.Hidden;
        }

        private void UpdateHostsTab(bool hideTab = true)
        {
            tviHost.Items.Clear();
            foreach (HostInfo host in powerShellComm.adminEntity.Hosts)
            {
                TreeViewItem hostItem = null;
                if (host.Status == ServiceStatus.Up)
                {
                    hostItem = CreateTreeViewItem(host.HostName, "Started-16.png");
                }
                else if (host.Status == ServiceStatus.Down)
                {
                    hostItem = CreateTreeViewItem(host.HostName, "Stopped-16.png");
                }
                else if (host.Status == ServiceStatus.Unknown)
                {
                    hostItem = CreateTreeViewItem(host.HostName, "Unknown-16.png");
                }
                else
                {
                    hostItem = CreateTreeViewItem(host.HostName, "Other-16.png");
                }
                tviHost.Items.Add(hostItem);
            }
            tviHost.IsExpanded = true;
            if (hideTab)
                rtHosts.Visibility = System.Windows.Visibility.Hidden;
        }

        private void tviHost_GotFocus(object sender, RoutedEventArgs e)
        {
            if (tviHost.Items.Count > 0 && !tviHost.IsSelected)
            {
                rtHosts.Visibility = System.Windows.Visibility.Visible;
                rtHosts.IsSelected = true;
            }
        }

        private void tviHost_LostFocus(object sender, RoutedEventArgs e)
        {
            rtHosts.Visibility = System.Windows.Visibility.Hidden;
        }

        private void tviCache_GotFocus(object sender, RoutedEventArgs e)
        {
            rtCache.Visibility = System.Windows.Visibility.Visible;
            if (tviCache.IsSelected) //Cache root is selected
            {
                rbCConfig.IsEnabled = false;
                rbCRemove.IsEnabled = false;
                rbCStatistics.IsEnabled = false;
            }
            else if (tviCache.Items.Count > 0 && !tviCache.IsSelected) //Cache item is selected
            {
                rbCConfig.IsEnabled = true;
                rbCRemove.IsEnabled = true;
                rbCStatistics.IsEnabled = true;
            }
            rtCache.IsSelected = true;
        }

        private void tviCache_LostFocus(object sender, RoutedEventArgs e)
        {
            rtCache.Visibility = System.Windows.Visibility.Hidden;
        }

        void message_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (powerShellComm.Message.MessgageText != null)
            {
                txtMessage.Text = powerShellComm.Message.MessgageText;
                if (powerShellComm.Message.MessageType == MessageType.Error)
                {
                    txtMessage.Foreground = new SolidColorBrush(Colors.Red);
                }
                else
                {
                    txtMessage.Foreground = new SolidColorBrush(Colors.Green);
                }
            }
        }

        private TreeViewItem CreateTreeViewItem(string header, string iconName)
        {
            TreeViewItem child = new TreeViewItem();
            StackPanel pan = new StackPanel();
            if (iconName != null)
            {
                pan.Orientation = System.Windows.Controls.Orientation.Horizontal;
                Uri src = new Uri("pack://application:,,/Images/Icons/" + iconName);
                BitmapImage img = new BitmapImage(src);
                Image image = new Image();
                image.Width = 16;
                image.Height = 16;
                image.Source = img;
                pan.Children.Add(image);
            }
            TextBlock text = new TextBlock();
            text.Text = " " + header;
            pan.Children.Add(text);
            child.Header = pan;
            return child;
        }

        private void btnClosePanel_Click(object sender, RoutedEventArgs e)
        {
            pnlCacheStatistics.Visibility = System.Windows.Visibility.Hidden;
        }

        private void amiAbout_Click(object sender, RoutedEventArgs e)
        {
            About aboutWindow = new About();
            aboutWindow.Owner = this;
            aboutWindow.ShowDialog();
        }

        private void amiExit_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        #endregion

    }
}
